package cn.edu.gdu.quizpractice.service.impl;

import cn.edu.gdu.quizpractice.dao.UserDao;
import cn.edu.gdu.quizpractice.entity.User;
import cn.edu.gdu.quizpractice.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

// --- 导入 ---
import cn.edu.gdu.quizpractice.dto.request.LoginRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import cn.edu.gdu.quizpractice.common.utils.WeChatDecryptUtils; // 引入解密工具类
// --- 导入结束 ---

/**
 * @Author: Aubery
 * @Date: 2025-04-21-18:38
 * @Description:
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements IUserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class); // 添加 Logger

    // ... (依赖注入: RestTemplate, wx.appid, wx.secret, wx.code2SessionUrl) ...
     @Autowired
    private RestTemplate restTemplate; // 注入 RestTemplate

    @Value("${wx.appid}") // 修正占位符以匹配 application.yml
    private String appId;

    @Value("${wx.secret}") // 修正占位符以匹配 application.yml
    private String appSecret;

    @Value("${wx.code2SessionUrl}")
    private String code2SessionUrl;
    
    @Override
    public User findByOpenid(String openid) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid);
        User user = this.getOne(queryWrapper);
        if (user != null) {
            user.setSessionKey(null); // 不返回 sessionKey
        }
        return user;
    }

    @Override
    public User login(LoginRequest loginRequest) {
        String url = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                                   code2SessionUrl, appId, appSecret, loginRequest.getCode());

        log.info("调用微信 code2Session API (URL不含敏感信息): {}", code2SessionUrl);
        String response = restTemplate.getForObject(url, String.class);
        log.debug("微信 API 响应: {}", response); // debug 级别

        JSONObject jsonResponse = JSON.parseObject(response);
        String openid = jsonResponse.getString("openid"); // 注意字段名是 openid
        String sessionKey = jsonResponse.getString("session_key"); // sessionKey 是 Base64 编码的
        Integer errcode = jsonResponse.getInteger("errcode");
        String errmsg = jsonResponse.getString("errmsg");

        if (errcode != null && errcode != 0) {
            log.error("微信登录失败: errcode={}, errmsg={}", errcode, errmsg);
            throw new RuntimeException("微信登录失败: " + errmsg);
        }

        if (openid == null) {
             log.error("获取 openid 失败，微信 API 响应: {}", response);
             throw new RuntimeException("获取微信 openid 失败");
        }

        // 查询用户是否存在 (findByOpenid 不返回 sessionKey，所以这里用 getOne)
        QueryWrapper<User> userQuery = new QueryWrapper<User>().eq("openid", openid);
        User user = this.getOne(userQuery);
        boolean isNewUser = (user == null);

        LocalDateTime now = LocalDateTime.now();

        // ---- 解密用户信息 ----
        JSONObject decryptedUserInfo = null;
        if (loginRequest.getEncryptedData() != null && loginRequest.getIv() != null && sessionKey != null) {
            log.info("尝试解密用户信息...");
            decryptedUserInfo = WeChatDecryptUtils.decryptData(
                    loginRequest.getEncryptedData(),
                    sessionKey, // 传递 Base64 编码的 sessionKey
                    loginRequest.getIv());

            if (decryptedUserInfo != null) {
                log.info("用户信息解密成功。");
                // 安全校验：解密出的 openid 是否与 code2Session 返回的一致
                String decryptedOpenid = decryptedUserInfo.getString("openId"); // 解密后字段是 openId
                if (!openid.equals(decryptedOpenid)) {
                    log.error("安全校验失败：解密后的 openid ({}) 与 code2Session 返回的 openid ({}) 不一致！", decryptedOpenid, openid);
                    throw new RuntimeException("用户身份校验失败");
                }
            } else {
                log.warn("用户信息解密失败，将使用 LoginRequest 中的可选信息（如果提供）。");
            }
        } else {
             log.info("未提供加密数据或IV，跳过用户信息解密。");
        }
        // ---- 解密结束 ----

        if (!isNewUser) {
            // 用户已存在
            log.info("用户已存在: openid={}", openid);
            user.setSessionKey(sessionKey); // 更新数据库中 Base64 编码的 sessionKey
            user.setLastLoginTime(now);

            // 更新用户信息：优先使用解密数据
            updateUserInfo(user, decryptedUserInfo, loginRequest);

            this.updateById(user);
        } else {
            // 用户不存在，创建新用户
            log.info("用户不存在，创建新用户: openid={}", openid);
            user = new User();
            user.setOpenid(openid);
            user.setSessionKey(sessionKey); // 存储 Base64 编码的 sessionKey
            user.setCreateTime(now);
            user.setLastLoginTime(now);
            user.setStatus(1); // 默认状态正常

            // 填充用户信息：优先使用解密数据
            updateUserInfo(user, decryptedUserInfo, loginRequest);

            this.save(user);
            log.info("新用户创建成功: id={}, openid={}", user.getId(), user.getOpenid());
        }

        // 清理敏感信息后返回
        user.setSessionKey(null);
        // user.setOpenid(null); // 可选

        return user;
    }

    /**
     * 更新用户信息，优先使用解密后的数据
     * @param user 要更新的 User 对象
     * @param decryptedUserInfo 解密后的 JSONObject，可能为 null
     * @param loginRequest 原始登录请求，包含可选的用户信息
     */
    private void updateUserInfo(User user, JSONObject decryptedUserInfo, LoginRequest loginRequest) {
        if (decryptedUserInfo != null) {
            // 优先使用解密数据 (注意解密后的 JSON 字段名)
            user.setNickname(decryptedUserInfo.getString("nickName"));
            user.setAvatarUrl(decryptedUserInfo.getString("avatarUrl"));
            user.setGender(decryptedUserInfo.getInteger("gender"));
            user.setCountry(decryptedUserInfo.getString("country"));
            user.setProvince(decryptedUserInfo.getString("province"));
            user.setCity(decryptedUserInfo.getString("city"));
            user.setLanguage(decryptedUserInfo.getString("language"));
            // 如果需要 unionId，也可以在这里设置
            // if (decryptedUserInfo.containsKey("unionId")) {
            //     user.setUnionId(decryptedUserInfo.getString("unionId"));
            // }
        } else {
             // 解密失败或未提供，使用 LoginRequest 中的数据 (如果存在)
             if (loginRequest.getNickName() != null) user.setNickname(loginRequest.getNickName());
             if (loginRequest.getAvatarUrl() != null) user.setAvatarUrl(loginRequest.getAvatarUrl());
             if (loginRequest.getGender() != null) user.setGender(loginRequest.getGender());
             if (loginRequest.getCountry() != null) user.setCountry(loginRequest.getCountry());
             if (loginRequest.getProvince() != null) user.setProvince(loginRequest.getProvince());
             if (loginRequest.getCity() != null) user.setCity(loginRequest.getCity());
             if (loginRequest.getLanguage() != null) user.setLanguage(loginRequest.getLanguage());
        }
    }

    // 旧的 updateUserInfoIfProvided 方法不再需要，已被 updateUserInfo 替代
}
